use bliquez::{
    material::attribute::Uniform,
    misc::{vertices::v3dc, ShapeBatch},
    Context, Material, Scene, COLOR_BLACK, COLOR_BLUE, COLOR_CYAN, COLOR_GREEN, COLOR_PURPLE,
    COLOR_RED, COLOR_WHITE, COLOR_YELLOW,
};
use cgmath::{perspective, point3, vec3, Deg, Matrix4, Rad};
use winit::{
    dpi::PhysicalSize,
    event::{Event, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::WindowBuilder,
};


fn main() {
    let el = EventLoop::new().unwrap();
    let window = WindowBuilder::new()
        .with_title("Hello Cube")
        .with_inner_size(PhysicalSize {
            width: 800,
            height: 800,
        })
        .build(&el)
        .unwrap();

    let mut ctx = Context::new(&window, 800, 800);

    let mut scene = Scene::new(wgpu::Color::BLACK);
    scene.put_global(
        0,
        Material::builder()
            .attr(
                Uniform::new(
                    &ctx,
                    perspective(Deg(75.0f32), 1.0, 0.01, 100.0)
                        * Matrix4::look_at_rh(
                            point3(2.0, 2.0, 2.0),
                            point3(0.0, 0.0, 0.0),
                            vec3(0.0, 1.0, 0.0),
                        ),
                ),
                wgpu::ShaderStages::VERTEX,
            )
            .build(&ctx),
    );

    let mut batch = ShapeBatch::new(&ctx, &scene);
    batch.mesh_mut().add(
        [
            v3dc(0.0, 0.0, 0.0, COLOR_BLACK),  // 0
            v3dc(1.0, 0.0, 0.0, COLOR_RED),    // 1
            v3dc(0.0, 1.0, 0.0, COLOR_GREEN),  // 2
            v3dc(1.0, 1.0, 0.0, COLOR_YELLOW), // 3
            v3dc(0.0, 0.0, 1.0, COLOR_BLUE),   // 4
            v3dc(0.0, 1.0, 1.0, COLOR_CYAN),   // 5
            v3dc(1.0, 0.0, 1.0, COLOR_PURPLE), // 6
            v3dc(1.0, 1.0, 1.0, COLOR_WHITE),  // 7
        ],
        [
            0, 2, 5, 0, 5, 4, // Left
            6, 7, 3, 6, 3, 1, // Right
            0, 4, 6, 0, 6, 1, // Bottom
            5, 2, 3, 5, 3, 7, // Top
            4, 5, 7, 4, 7, 6, // Front
            1, 3, 2, 1, 2, 0, // Back
        ],
    );
    scene.add_brick("batch", batch);

    let mut theta = 0.0;

    el.set_control_flow(ControlFlow::Poll);
    el.run(|event, target| match event {
        Event::WindowEvent {
            event: WindowEvent::CloseRequested,
            ..
        } => target.exit(),
        Event::AboutToWait => {
            theta += 0.0001;
            let batch = scene.get_brick_mut::<ShapeBatch>("batch").unwrap();
            batch
                .material_mut()
                .attr_mut::<Uniform<Matrix4<f32>>>(0)
                .unwrap()
                .set_data(
                    Matrix4::from_angle_y(Rad(theta))
                        * Matrix4::from_translation(-vec3(0.5, 0.5, 0.5)),
                );
            window.request_redraw();
        }
        Event::WindowEvent {
            event: WindowEvent::KeyboardInput { event, .. },
            ..
        } => if event.state.is_pressed() {},
        Event::WindowEvent {
            event: WindowEvent::Resized(size),
            ..
        } => {
            scene
                .global_mut(0)
                .and_then(|m| m.attr_mut::<Uniform<Matrix4<f32>>>(0))
                .unwrap()
                .set_data(
                    perspective(
                        Deg(45.0),
                        size.width as f32 / size.height as f32,
                        0.01,
                        100.0,
                    ) * Matrix4::look_at_rh(
                        point3(2.0, 2.0, 2.0),
                        point3(0.0, 0.0, 0.0),
                        vec3(0.0, 1.0, 0.0),
                    ),
                );
            ctx.resize(size.width, size.height);
        }
        Event::WindowEvent {
            event: WindowEvent::RedrawRequested,
            ..
        } => ctx.render_scene(&mut scene),
        _ => (),
    })
    .unwrap();
}
